﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace Assist
{
	public class WallAssistFunc
	{
		public static WallDatum GetWallDatum(Document doc, Wall wall)
		{
			WallDatum wallDatum = new WallDatum();
			Parameter parameter = wall.get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM);
			WallType wallType = RevitVersionFuncs.GetElement(doc, parameter.AsElementId()) as WallType;
			wallDatum.wallType = wallType;
			wallDatum.curveType = WallAssistFunc.GetWallCurveType(wall);
			wallDatum.level = WallAssistFunc.GetWallBottomAssoLevel(doc, wall);
			wallDatum.idTopLevel = wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
			if (wallType.Kind == null)
			{
				parameter = wallType.get_Parameter(BuiltInParameter.WALL_ATTR_WIDTH_PARAM);
				double val = parameter.AsDouble();
				wallDatum.width = AssistFunc.feetToMM(val);
			}
			else
			{
				WallKind kind = wallType.Kind;
			}
			wallDatum.ptStart = WallAssistFunc.GetStartPt(wall);
			wallDatum.ptEnd = WallAssistFunc.GetEndPt(wall);
			return wallDatum;
		}

		public static Level GetWallBottomAssoLevel(Document doc, Wall wall)
		{
			ElementId id = wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).AsElementId();
			return RevitVersionFuncs.GetElement(doc, id) as Level;
		}

		public static IList<FamilyInstance> GetWallAssoDoorWins(Document doc, Wall wall, BuiltInCategory category)
		{
			Level level = null;
			return WallAssistFunc.GetWallAssoDoorWins(doc, wall, category, level);
		}

		public static IList<FamilyInstance> GetWallAssoDoorWins(Document doc, Wall wall, BuiltInCategory category, Level level)
		{
			IList<FamilyInstance> list = null;
			ElementCategoryFilter elementCategoryFilter = new ElementCategoryFilter(category);
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).WherePasses(elementCategoryFilter).ToElements())
			{
				FamilyInstance familyInstance = element as FamilyInstance;
				Element host = familyInstance.Host;
				if (host != null)
				{
					ElementId obj = host.get_Parameter(BuiltInParameter.ID_PARAM).AsElementId();
					if (wall.get_Parameter(BuiltInParameter.ID_PARAM).AsElementId().Equals(obj))
					{
						if (list == null)
						{
							list = new List<FamilyInstance>();
						}
						if (level == null)
						{
							list.Add(familyInstance);
						}
						else
						{
							object obj2 = familyInstance.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM).AsElementId();
							ElementId obj3 = level.get_Parameter(BuiltInParameter.ID_PARAM).AsElementId();
							if (obj2.Equals(obj3))
							{
								list.Add(familyInstance);
							}
						}
					}
				}
			}
			return list;
		}

		public static XYZ GetStartPt(Wall wall)
		{
			return (wall.Location as LocationCurve).Curve.GetEndPoint(0);
		}

		public static bool SetStartPt(Wall wall, XYZ pt)
		{
			Location location = wall.Location;
			return true;
		}

		public static XYZ GetEndPt(Wall wall)
		{
			return (wall.Location as LocationCurve).Curve.GetEndPoint(1);
		}

		public static WallCurveType GetWallCurveType(Wall wall)
		{
			WallCurveType result = WallCurveType.eError;
			LocationCurve locationCurve = wall.Location as LocationCurve;
			if (locationCurve.Curve as Line != null)
			{
				result = WallCurveType.eLineWall;
			}
			if (locationCurve.Curve as Arc != null)
			{
				result = WallCurveType.eArcWall;
			}
			return result;
		}

		public static Curve GetWallCurve(Wall wall)
		{
			return (wall.Location as LocationCurve).Curve;
		}

		public static double GetWallThick(Document doc, Wall wall)
		{
			Parameter parameter = wall.get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM);
			parameter = (RevitVersionFuncs.GetElement(doc, parameter.AsElementId()) as WallType).get_Parameter(BuiltInParameter.WALL_ATTR_WIDTH_PARAM);
			if (parameter == null)
			{
				return 0.0;
			}
			return AssistFunc.feetToMM(parameter.AsDouble());
		}

		public static bool ResetLineWall(Application app, Document doc, Wall wall, XYZ ptStart, XYZ ptEnd)
		{
			Line curve = app.CreatYJKLine(ptStart, ptEnd, true);
			(wall.Location as LocationCurve).Curve = curve;
			return true;
		}

		private const double precision = 1E-05;
	}
}
